/**
 * 全局指令文件
 */

import { store } from '@/store';
import { bindEvent, unbindEvent } from './utils';

/**
 * 替换掉非数字内容
 */
const replaceNumber = e => e.target.value = e.target.value.replace(/[^\d]+/, '');

/**
 * 限制只能输入数字
 */
const onlyNumber = {
    mounted: el => bindEvent(el, 'input', replaceNumber),
    beforeUnmount: el => unbindEvent(el, 'input', replaceNumber)
}

/**
 * 拖拽
 */
const drag = {
    mounted(el) {
        let isDragging = false;
        let offsetX, offsetY, parentRect, elRect;

        // 处理鼠标和触摸事件的通用逻辑
        const startDrag = (clientX, clientY) => {
            isDragging = true;

            // 计算点击位置与元素左上角的偏移量
            elRect = el.getBoundingClientRect();
            // 获取父元素的边界
            parentRect = el.parentElement.getBoundingClientRect();

            offsetX = clientX - elRect.left;
            offsetY = clientY - elRect.top;

            // 加速性能
            el.style.willChange = 'left,top';
            // 防止选中文本或页面滚动
            el.style.userSelect = 'none';
            el.style.touchAction = 'none';
        };

        const onDrag = (clientX, clientY) => {
            if (!isDragging) return;

            // 计算新的位置
            let newLeft = clientX - offsetX - parentRect.left;
            let newTop = clientY - offsetY - parentRect.top;

            // 限制在父元素内移动
            newLeft = Math.max(0, Math.min(newLeft, parentRect.width - elRect.width));
            newTop = Math.max(0, Math.min(newTop, parentRect.height - elRect.height));

            // 设置元素的新位置
            el.style.left = `${newLeft}px`;
            el.style.top = `${newTop}px`;
        };

        const stopDrag = () => {
            isDragging = false;
            el.style.userSelect = ''; // 恢复文本选中
            el.style.touchAction = '';
        };

        // 鼠标事件
        const onMouseDown = (e) => {
            startDrag(e.clientX, e.clientY);
            if (e.cancelable && !e.defaultPrevented && e.preventDefault) {
                e.preventDefault(); // 安全阻止
            }
        };

        const onMouseMove = (e) => {
            onDrag(e.clientX, e.clientY);
        };

        const onMouseUp = () => {
            stopDrag();
        };

        // 触摸事件
        const onTouchStart = (e) => {
            const touch = e.touches[0]; // 获取第一个触摸点
            startDrag(touch.clientX, touch.clientY);
        };

        const onTouchMove = (e) => {
            const touch = e.touches[0];
            onDrag(touch.clientX, touch.clientY);
        };

        const onTouchEnd = () => {
            stopDrag();
        };

        // 添加事件监听器
        el.addEventListener('mousedown', onMouseDown, { passive: false });
        document.addEventListener('mousemove', onMouseMove, { passive: false });
        document.addEventListener('mouseup', onMouseUp);

        el.addEventListener('touchstart', onTouchStart, { passive: false });
        document.addEventListener('touchmove', onTouchMove, { passive: false });
        document.addEventListener('touchend', onTouchEnd);

        // 在元素卸载时移除事件监听器
        el._onMouseDown = onMouseDown;
        el._onMouseMove = onMouseMove;
        el._onMouseUp = onMouseUp;
        el._onTouchStart = onTouchStart;
        el._onTouchMove = onTouchMove;
        el._onTouchEnd = onTouchEnd;
    },

    unmounted(el) {
        // 移除事件监听器
        el.removeEventListener('mousedown', el._onMouseDown);
        document.removeEventListener('mousemove', el._onMouseMove);
        document.removeEventListener('mouseup', el._onMouseUp);

        el.removeEventListener('touchstart', el._onTouchStart);
        document.removeEventListener('touchmove', el._onTouchMove);
        document.removeEventListener('touchend', el._onTouchEnd);
    },
}

/**
 * 横向拖动
 */
const dragX = {
    mounted(el) {
        if (window.innerWidth < 1280) return;
        const scrollContent = el.querySelector('.scroll-content');

        if (!scrollContent) {
            console.error('Scroll content not found. Ensure the directive is applied to a valid container.');
            return;
        }

        let startX = 0;
        let offset = 0;
        let isDragging = false;
        let velocity = 0;
        let lastTime = 0;
        let lastX = 0;
        let contentWidth = scrollContent.scrollWidth;
        let containerWidth = el.offsetWidth;

        const updateDimensions = () => {
            contentWidth = scrollContent.scrollWidth;
            containerWidth = el.offsetWidth;
        };

        const resizeObserver = new ResizeObserver(() => {
            updateDimensions();
        });
        resizeObserver.observe(scrollContent);

        const clampOffset = (value) => {
            return Math.max(-(contentWidth - containerWidth), Math.min(0, value));
        };

        const simulateInertia = () => {
            if (Math.abs(velocity) > 0.1) {
                offset -= velocity;
                velocity *= 0.9;
                offset = clampOffset(offset);
                scrollContent.style.transform = `translateX(${offset}px)`;
                requestAnimationFrame(simulateInertia);
            } else {
                offset = clampOffset(offset);
                scrollContent.style.transform = `translateX(${offset}px)`;
            }
        };

        const onMouseDown = e => {
            // 只处理左键点击
            if (e.button !== 0) return;
            if (e.cancelable && !e.defaultPrevented && e.preventDefault) {
                e.preventDefault(); // 安全阻止
            }
            isDragging = true;
            startX = e.pageX;
            offset = parseFloat(scrollContent.style.transform?.split('(')[1] || '0') || 0;
            lastTime = Date.now();
            lastX = e.pageX;
            el.style.cursor = 'grabbing';
            el.style.userSelect = 'none';
            cancelAnimationFrame(simulateInertia);
        };

        let animationFrameId = null;

        const onMouseMove = e => {
            if (!isDragging) return;

            // 检测是否移动了足够距离，认为是拖拽
            if (Math.abs(e.pageX - startX) > 5) {
                el.style.pointerEvents = 'none';
            }

            const updateTransform = () => {
                const deltaX = e.pageX - startX;
                offset = clampOffset(offset + deltaX);
                scrollContent.style.transform = `translateX(${offset}px)`;
                startX = e.pageX;
            };

            if (animationFrameId) cancelAnimationFrame(animationFrameId);
            animationFrameId = requestAnimationFrame(updateTransform);
        };

        const onMouseUp = (e) => {
            if (!isDragging) return;
            isDragging = false;
            el.style.cursor = 'grab';
            el.style.userSelect = '';
            el.style.pointerEvents = 'auto';
            requestAnimationFrame(simulateInertia);
        };

        el.addEventListener('mousedown', onMouseDown);
        window.addEventListener('mousemove', onMouseMove);
        window.addEventListener('mouseup', onMouseUp);

        const cleanup = () => {
            el.removeEventListener('mousedown', onMouseDown);
            window.removeEventListener('mousemove', onMouseMove);
            window.removeEventListener('mouseup', onMouseUp);
            resizeObserver.disconnect();
        };

        el._cleanup = cleanup;
    },
    beforeUnmount(el) {
        if (el._cleanup) {
            el._cleanup();
        }
    }
}

const permission = {
    mounted(el, binding) {
        const { value } = binding;
        if (!store.menus.some(c => c.Tag == value)) {
            // 或者完全移除元素
            el.parentNode && el.parentNode.removeChild(el)
        }
    }
}

export default app => {
    app.directive('number', onlyNumber);
    app.directive('drag', drag);
    app.directive('dragX', dragX);
    app.directive('permission', permission);
}